const jwt = require("jsonwebtoken");
const md5 = require("md5");
const multer = require("multer");
const fs = require("fs");
const path = require("path");
const { UploadError } = require("./errors");
const toc = require("markdown-toc");
// 格式返回的形式
exports.FormatJson = function (code, msg, data) {
    return {
        code,
        msg,
        data
    }
}

//解密
exports.verifyJson = async function (token) {
    const decretkey = md5(process.env.JWT_decretKey);
    token = token.split(" ");
    let result = await jwt.verify(token[1], decretkey);
    result = {
        id: result.id,
        loginId: result.loginId,
        name: result.name
    }
    return result;
}

// 判断路径是否存在不存在则创建文件夹
async function isFilesExit(path) {
    try {
        await fs.promises.stat(path);
    } catch {
        await fs.promises.mkdir(path);
    }
}

const storage = multer.diskStorage({
    // 文件存放路径
    destination: async function (req, file, cb) {
        const filePaths = path.resolve(__dirname, "../public/static/uploads");
        await isFilesExit(filePaths);
        cb(null, filePaths)
    },
    // 文件名
    filename: function (req, file, cb) {
        const extname = path.extname(file.originalname);
        const orginPath = path.basename(file.originalname, extname);
        const newPath = `${orginPath}-${Date.now()}-${Math.round(Math.random() * 9000 + 1000)}${extname}`;
        cb(null, newPath)
    }
})

exports.uploading = multer({
    storage,
    limits: {
        fileSize: 1024 * 1024 * 3,
        files: 6
    },
    // 文件过滤只有为图片形式的才可以通过，其他的会被拦截下来
    fileFilter(req, file, cb) {
        const whiteBlanck = [".webp", ".jpg", ".png", ".jpeg", ".gif", ".pdf"];// 后缀名白名单
        const fileExt = path.extname(file.originalname);
        // 进行判断内容
        if (!whiteBlanck.includes(fileExt)) {
            cb(null, false)
            return;
        }
        cb(null, true);
    }
})

// 处理toc格式的内容
module.exports.handleToc = function (info) {
    const result = toc(info.markdownContent).json;//将marKdownContent格式的转换为json格式
    console.log(result, 'result')
    // 返会处理好的toc格式内容
    function transfer(flatArr) {
        const stackArr = [];// 模拟栈的数组
        const resultArr = []; // 最终输出toc的数组
        //创建好toc的对象
        function createTocItem(item) {
            return {
                name: item.content,
                anchor: item.slug,
                level: item.lvl,
                children: []
            }
        }

        // 进行递归处理
        function handleItem(item) {
            const top = stackArr[stackArr.length - 1];
            if (!top) { //若栈没有就是第一个 ，直接存储在栈里面
                stackArr.push(item);
                // 如果下一个等级比他高就加入其子元素中
            } else if (item.level > top.level) {
                top.children.push(item);
                stackArr.push(item);
            } else {
                // 没有就移除直到有为止
                stackArr.pop();
                handleItem(item);
            }
        }

        // 获取最小的标签内容
        let min = 6;
        for (const item of flatArr) {
            if (item.lvl < min) {
                min = item.lvl;
            }
        }

        // 进行调用
        for (const item of flatArr) {
            const tocItem = createTocItem(item);
            if (tocItem.level == min) {
                resultArr.push(tocItem);
            }
            handleItem(tocItem)
        }
        return resultArr;
    }
    info.toc = transfer(result);
    // 处理htmlContent中标签的不同内容
    for (const i of result) {
        switch (i.lvl) {
            case 1: {
                const newStr = `<h1 id='${i.slug}'>`;
                info.htmlContent = info.htmlContent.replace('<h1>', newStr);
                break;
            }
            case 2: {
                const newStr = `<h2 id='${i.slug}'>`;
                info.htmlContent = info.htmlContent.replace('<h2>', newStr);
                break;
            }
            case 3: {
                const newStr = `<h3 id='${i.slug}'>`;
                info.htmlContent = info.htmlContent.replace('<h3>', newStr);
                break;
            }
            case 4: {
                const newStr = `<h4 id='${i.slug}'>`;
                info.htmlContent = info.htmlContent.replace('<h4>', newStr);
                break;
            }
            case 5: {
                const newStr = `<h5 id='${i.slug}'>`;
                info.htmlContent = info.htmlContent.replace('<h5>', newStr);
                break;
            }
            case 6: {
                const newStr = `<h6 id='${i.slug}'>`;
                info.htmlContent = info.htmlContent.replace('<h6>', newStr);
                break;
            }
        }
    }
    return info;
}